#pragma once
#include <cuda_runtime.h>
#include <cmath>

const bool debug = true;

namespace gc {
	using uint = unsigned int;
	using uint64 = unsigned long long int;
	using Float = float;
	using Point3f = float3;

	#define blockSizeWithSMem  512;  // block size when using shared memory

	#define FMAX  3.402823466e+38F
	#define FMIN  1.175494351e-38F
	#define EPS   1e-06F
	#define PI    3.1415926535898F

	#define makePoint3f(x,y,z) make_float3(x,y,z)

	inline __host__ __device__ Point3f operator - (const Point3f &a, const Point3f &b) {
		return makePoint3f(a.x - b.x, a.y - b.y, a.z - b.z);
	}

	inline __host__ __device__ Point3f operator + (const Point3f &a, const Point3f &b) {
		return makePoint3f(a.x + b.x, a.y + b.y, a.z + b.z);
	}

	inline __host__ __device__  Point3f operator * (const Point3f &a, const Float k) {
		return makePoint3f(a.x * k, a.y * k, a.z * k);
	}

	inline __host__ __device__ Float length(const Point3f &a) {
		return sqrt(a.x*a.x + a.y*a.y + a.z*a.z);
	}

	inline __host__ __device__ Float sqr_length(const Point3f &a) {
		return (a.x*a.x + a.y*a.y + a.z*a.z);
	}

	inline __host__ __device__ Point3f normalize(const Point3f &a) {
		Float len = sqrt(a.x*a.x + a.y*a.y + a.z*a.z);
		return a * (1. / len);
	}

	inline __host__ __device__ Float dot(const Point3f &a, const Point3f &b) {
		return a.x*b.x + a.y*b.y + a.z*b.z;
	}
}